/*
 * Copyright the original author or authors.
 * 
 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *	  http://www.mozilla.org/MPL/MPL-1.1.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 package com.googlecode.milib.service.singleton {
	import com.googlecode.milib.MILibMain;
	import com.googlecode.milib.base.MLBroadcastClass;

	import flash.display.Stage;
	import flash.events.MouseEvent;

	/**
	 * @author Marek Brun
	 */
	public class MouseService extends MLBroadcastClass {
		
		//DATA: MouseEvent
		public const event_Down : String = 'Down';				//DATA: MouseEvent		public const event_Up : String = 'Up';				//DATA: MouseEvent		public const event_Leave : String = 'Leave';				public const event_Arrive : String = 'Arrive';				//DATA: MouseEvent		public const event_Move : String = 'Move';				public const event_MoveWhenDown : String = 'MoveWhenDown';				//DATA: MouseEvent
//		bubbles true 
//		buttonDown true if the primary mouse button is pressed; false otherwise. 
//		cancelable false; the default behavior cannot be canceled. 
//		ctrlKey true if the Control key is active; false if it is inactive. 
//		currentTarget The object that is actively processing the Event object with an event listener. 
//		delta The number of lines that that each notch on the mouse wheel represents. 
//		localX The horizontal coordinate at which the event occurred relative to the containing sprite. 
//		localY The vertical coordinate at which the event occurred relative to the containing sprite. 
//		shiftKey true if the Shift key is active; false if it is inactive. 
//		stageX The horizontal coordinate at which the event occurred in global stage coordinates. 
//		stageY The vertical coordinate at which the event occurred in global stage coordinates. 
//		target The InteractiveObject instance under the pointing device. The target is not always the object in the display list that registered the event listener. Use the currentTarget property to access the object in the display list that is currently processing the event.		public const event_Whell : String = 'Whell';		
		private static var instance:MouseService;				private var isLeave:Boolean;				private var isDown:Boolean;		
		private var lastVX:Number=0;		
		private var lastVY:Number=0;		
		private var stage:Stage;		
		private var lastX:Number=0;		private var lastY:Number=0;		
		private var downX:Number=0;		private var downY:Number=0;
		private var lastX2:Number=0;
		private var lastY2:Number=0;
		
		public function MouseService(access:Private) {
			stage=MILibMain.getInstance().getStage();
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown, false, 0, true);			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp, false, 0, true);			stage.addEventListener('mouseLeave', onMouseLeave, false, 0, true);			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove, false, 0, true);			stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWhell, false, 0, true);			isLeave=true;			isDown=false;
			lastVX=0;
			lastVY=0;
			lastX=stage.mouseX;
			lastY=stage.mouseY;
		}				public function getIsDown():Boolean {			return isDown;		}				public function getIsLeave():Boolean {			return isLeave;		}
		
		public function getDragVX():Number {
			if(isDown){ return downX-stage.mouseX; } 
			else{ return 0; }
		}
		
		public function getDragVY():Number {
			if(isDown){ return downY-stage.mouseY; } 
			else{ return 0; }
		}
		
		public function getLastVX():Number { return lastVX; }
		public function getLastVY():Number { return lastVY; }
		
		public function getX():Number { return stage.mouseX; }
		public function getY():Number { return stage.mouseY; }
		
		public function getLastX():Number { return lastX; }
		public function getLastY():Number { return lastY; }
		
		public function getLastX2():Number { return lastX2; }
		public function getLastY2():Number { return lastY2; }
		
		public static function getInstance():MouseService {
			if(instance){ return instance; } 
			else{ instance=new MouseService(null); return instance; }
		}
		
//********************************************************************************************
//		events for MouseService
//********************************************************************************************	
		protected function onMouseDown(event:MouseEvent):void {			isDown=true;
			broadcastEvent(event_Down, event);
		}				protected function onMouseUp(event:MouseEvent):void {			isDown=false;			broadcastEvent(event_Up, event);		}				protected function onMouseLeave(event:*):void {
			if(isDown){
				isDown=false;
				broadcastEvent(event_Up, event);
			}			isLeave=true;			broadcastEvent(event_Leave, event);		}				protected function onMouseMove(event:MouseEvent):void {
			lastVX=stage.mouseX-lastX;
			lastVY=stage.mouseY-lastY;
			
			lastX2=lastX;			lastY2=lastY;
			lastX=stage.mouseX;
			lastY=stage.mouseY;
						if(isLeave){				isLeave=false;				broadcastEvent(event_Arrive, event);			}			broadcastEvent(event_Move, event);			if(isDown){				broadcastEvent(event_MoveWhenDown);			}		}				protected function onMouseWhell(event:MouseEvent):void {			broadcastEvent(event_Whell, event);		}
		
	}
}

internal class Private {}
